<?php
/**
 * @package    system
 * @subpackage service
 */

/**
 * Service validator
 * Provides validation to any service, validating input and output datas
 */
class ServiceValidator
{
    /**
     * If the validator will be validate the input data
     * @var bool
     */
    static $validateInput = true;

    /**
     * If the validator will be validate the output data
     * @var bool
     */
    static $validateOutput = true;

    /**
     * Validate input
     *
     * @param object $data
     * @param string $class
     * @param string $method
     */
    static function validateInput($data, $class, $method)
    {
        if(self::$validateInput) {
            self::validateData($data, $class, $method, ServicesSchemas::INPUT_SCHEMA);
        }
    }

    /**
     * Validate output
     *
     * @param object $data
     * @param string $class
     * @param string $method
     */
    static function validateOutput($data, $class, $method)
    {
        if(self::$validateOutput) {
            self::validateData($data, $class, $method, ServicesSchemas::OUTPUT_SCHEMA);
        }
    }

    /**
     * Verify input data agains JSON Schema
     *
     * @throw ServiceValidationException
     * @param object $data
     * @param string $class the service name
     * @param string $method the services method name
     */
    static function validateData($data, $class, $method, $schemaType)
    {
        JsonSchema::$checkMode = JsonSchema::CHECK_MODE_TYPE_CAST;
        $jsonSchema = ServicesSchemas::getSchema($class,$method,$schemaType);
        $response = JsonSchema::validate($data,$jsonSchema,JsonFormatValidator::build());
        if(!$response->valid) {
            if($schemaType == ServicesSchemas::OUTPUT_SCHEMA) {
                $msg = 'Service Output for *'.$class.'::'.$method.' - '
                    . ServicesSchemas::getSchemaTypeName($schemaType)
                    . '* has broken the defined json schema contract.';
                if(JsonSchema::$checkMode == JsonSchema::CHECK_MODE_NORMAL) {
                    $msg .= ' ( JsonSchema::checkMode => normal ) ';
                }
                if(JsonSchema::$checkMode == JsonSchema::CHECK_MODE_TYPE_CAST) {
                    $msg .= ' ( JsonSchema::checkMode => type cast ) ';
                }
                $msg .= "\n";
                foreach($response->errors as $error) {
                    $msg .= "\n" . $error['property'] . ' ==> ' . $error['message'] . " \n ";
                }
                throw new ServiceBrokenOutputContractException($msg);
            }
            else {
                $msg = 'Service Validation Error for '.$class.'::'.$method.' - ' . ServicesSchemas::getSchemaTypeName($schemaType);
                foreach($response->errors as $error) {
                    $msg .= "\n" . $error['property'] . ' ==> ' . $error['message'] . " \n ";
                }
                throw new ServiceValidationException($msg,null,$response->errors);
            }
        }
    }
}
?>